package com.self.lock;

public class SelfSemaphore {

    private final int cap;
    private int permit;

    public SelfSemaphore(int permit) {
        this.cap = permit;
        this.permit = permit;
    }

    public synchronized boolean tryAcquire() throws InterruptedException {
        return tryAcquire(0);
    }

    public synchronized boolean tryAcquire(long timeout) throws InterruptedException {

        if(timeout < 0) {
            timeout = 0;
        }

        boolean timed = timeout > 0;

        long deadline = System.currentTimeMillis() + timeout;

        if(!timed && this.permit <= 0) {
            return false;
        }

        while (this.permit <= 0) {
            wait(timeout);
            if(System.currentTimeMillis() >= deadline) {
                return false;
            }
        }

        this.permit--;

        return true;
    }

    public synchronized void acquire() throws InterruptedException {

        while (this.permit <= 0) {
            wait();
        }

        this.permit--;
    }

    public synchronized void release() {
        if(this.permit == this.cap) {
            return;
        }

        this.permit++;
        notifyAll();
    }
}
